/**
 * All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
 * <p>
 * MeetManageService
 * 会议管理
 * <p>
 * 修改纪录
 * 2020-08-14 版本：1.0 wanghongwei 创建。
 *
 * @version 版本：1.0
 * @author 作者：wanghongwei
 * 创建日期：2020-08-14
 */
package com.topscomm.meet.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.topscomm.base.BaseRemindTemplate;
import com.topscomm.base.BaseSystemConst;
import com.topscomm.base.BaseSystemConst.NoticeTypeEnum;
import com.topscomm.base.pojo.*;
import com.topscomm.base.service.*;
import com.topscomm.base.service.impl.BasePermissionManageHistoryService;
import com.topscomm.base.service.impl.BaseRemindConfigHistoryService;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.cbo.pojo.CboDeptEntity;
import com.topscomm.cbo.pojo.CboUserEntity;
import com.topscomm.cbo.service.ICboAttachmentService;
import com.topscomm.cbo.service.ICboDeptService;
import com.topscomm.cbo.service.impl.CboUserService;
import com.topscomm.meet.MeetSystemConst;
import com.topscomm.meet.MeetSystemConst.MeetPersonTypeEnum;
import com.topscomm.meet.MeetSystemConst.MeetRoomTypeEnum;
import com.topscomm.meet.MeetSystemConst.MeetStateEnum;
import com.topscomm.meet.pojo.*;
import com.topscomm.meet.service.*;
import com.topscomm.meet.service.impl.auto.MeetManageServiceAuto;
import com.topscomm.meet.vo.OAResult;
import com.topscomm.pub.util.*;
import com.topscomm.tap.common.DatacodeCache;
import com.topscomm.tap.common.ParameterCache;
import com.topscomm.tap.common.SessionUserBean;
import com.topscomm.tap.security.SecurityUserDetails;
import com.topscomm.tap.threadlocal.ThreadLocalContext;
import com.topscomm.work.WorkSystemConst.WorkHandleUserEnum;
import com.topscomm.work.WorkSystemConst.WorkSourceAppEnum;
import com.topscomm.work.WorkSystemConst.WorkSourceTypeEnum;
import com.topscomm.work.pojo.WorkScheduleEntity;
import com.topscomm.work.service.IWorkScheduleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.curator.shaded.com.google.common.base.Objects;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.topscomm.base.BaseRemindTemplate.AppRemindTemplate;

@Slf4j
@Service(value = "meetManageService")
@Scope(value = "singleton")
public class MeetManageService extends MeetManageServiceAuto implements IMeetManageService {
    private final MeetManageService self;

    public MeetManageService(@Lazy MeetManageService self) {
        this.self = self;
    }

    @Autowired
    DatacodeCache datacodeCache;
    @Autowired
    private IMeetRoomApplyService meetRoomApplyService;
    @Autowired
    private IMeetRecordService meetRecordService;
    @Autowired
    private IBasePermissionManageService basePermissionManageService;
    @Autowired
    private IBaseRemindConfigService baseRemindConfigService;
    @Autowired
    private IMeetPersonRecordService meetPersonRecordService;
    @Autowired
    private IWorkScheduleService workScheduleService;
    @Autowired
    private IMeetTypeManageService meetTypeManageService;
    @Autowired
    private IBaseOperateRecordService baseOperateRecordService;
    @Autowired
    private IMeetAgendaService meetAgendaService;
    @Autowired
    private IBaseRemindTaskService baseRemindTaskService;
    @Autowired
    private CboUserService cboUserService;
    @Autowired
    private ICboDeptService cbodeptservice;
    @Autowired
    private IFileManageService fileManageService;
    @Autowired
    private ISmsWorkTasksCloseService smsWorkTasksCloseService;
    @Autowired
    @Qualifier("securityUserDetailsService")
    private UserDetailsService userDetailsService;
    @Resource(name = "baseRemindConfigHistoryService")
    private BaseRemindConfigHistoryService baseRemindConfigHistoryService;

    @Autowired
    private IBaseCboUserExtendService baseCboUserExtendService;

    // 生成会议二维码对应的图片的sourcetype
    private static final String AttachmentMeetJoinSourceType = "meetJoin";

    @Autowired
    private ICboAttachmentService cboAttachmentService;
    @Resource(name = "meetManageHistoryService")
    private MeetManageHistoryService meetManageHistoryService;
    @Resource(name = "basePermissionManageHistoryService")
    private BasePermissionManageHistoryService basePermissionManageHistoryService;
    @Resource(name = "meetPersonRecordHistoryService")
    private MeetPersonRecordHistoryService meetPersonRecordHistoryService;
    @Autowired
    private MeetRoomManageService meetRoomManageService;

    /**
     * 批量删除会议
     *
     * @param ids
     * @return
     * @description:
     * @author: donghang
     * @date: 2020年11月10日下午4:10:01
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(String ids) {
        String[] meetIds = ids.split(",");
        String meetSql = "";
        for (String meetId : meetIds) {
            meetSql += "'" + meetId + "'" + ",";
        }
        if (meetSql.length() > 0) {
            meetSql = meetSql.substring(0, meetSql.length() - 1);
        }
        StringBufferProxy sqlBufferProxy = new StringBufferProxy();
        // 1.删除会议自身关联信息
        sqlBufferProxy.clear();
        sqlBufferProxy.appendSingle("sourceid in({0}) and sourcetype='{1}'", meetSql, MeetManageEntity.tableName);
        this.baseRemindConfigService.deleteByWhere(sqlBufferProxy.toString());
        this.baseOperateRecordService.deleteByWhere(sqlBufferProxy.toString());
        this.basePermissionManageService.deleteByWhere(sqlBufferProxy.toString());
        sqlBufferProxy.clear();
        sqlBufferProxy.appendLineSingle("meetid in ({0})", meetSql);
        this.meetPersonRecordService.deleteByWhere(sqlBufferProxy.toString());
        this.meetAgendaService.deleteByWhere(sqlBufferProxy.toString());
        // 2.删除日程
        this.workScheduleService.cancelWorkSchedule(WorkSourceAppEnum.Meet, MeetManageEntity.tableName, ids);
        // 3.删除会议信息
        sqlBufferProxy.clear();
        sqlBufferProxy.appendSingle("id in({0})", meetSql);
        return this.deleteByWhere(sqlBufferProxy.toString());
    }

    /**
     * 查询会议室的近期占用记录，主要兼容部门级会议室,部门会议室不走申请
     *
     * @param paraMap
     * @return
     * @description:
     * @author: donghang
     * @date: 2020年10月28日上午11:05:14
     * @modify:
     */
    @Override
    public List<Map<String, Object>> queryMeetRoomRecentlyApplyList(Map<String, Object> paraMap) {
        List<Map<String, Object>> applyList = new ArrayList<>();
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("enabled=1 and state in (1) and meetroomid is not null and meetroomtype='{0}'",
                MeetRoomTypeEnum.Dept);
        if (paraMap.containsKey("qry_begintime")) {
            String start = paraMap.get("qry_begintime").toString();
            sql.appendSingle(" and endtime > {0}", SQLAdapter.toDateLong(start));
        }
        if (paraMap.containsKey("qry_endtime")) {
            String end = paraMap.get("qry_endtime").toString();
            sql.appendSingle(" and begintime < {0} ", SQLAdapter.toDateLong(end));
        }
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("qry_wheresql", sql.toString());
        applyList.addAll(this.queryMap(queryMap, "queryMeetApplyInfoList"));
        return applyList;
    }

    /**
     * @param dataMap
     * @param flowIdList
     * @return
     * @description: 是否需要进行会议室审批, 只有公司级及线上会议室走审批
     * @author: wanghongwei
     * @date: 2020-11-2 14:20:49
     * @modify:
     */
    private boolean isApplyMeetRoom(Map<String, Object> dataMap) {
        String meetRoomType = ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldMeetroomtype));
        String remoteRoomid = ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldRemoteroomid));
        return  Objects.equal(meetRoomType, MeetSystemConst.MeetRoomTypeEnum.Company) || !remoteRoomid.isEmpty() ;
    }

    /**
     * @param dataMap
     * @param userBean
     * @return
     * @description: 得到会议室申请的实例对象
     * @author: wanghongwei
     * @date: 2020-10-31 10:02:53
     * @modify:
     */
    private MeetRoomApplyEntity getMeetRoomApplyEntity(String roomType, Map<String, Object> dataMap, SessionUserBean userBean) {
        MeetRoomApplyEntity entity = new MeetRoomApplyEntity();
        // 会议基本信息
        entity.setName(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldName)));
        entity.setBoardcontent(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldContent)));
        entity.setBegintime(
                DateUtil.stringToDate(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldBegintime))));
        entity.setEndtime(
                DateUtil.stringToDate(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldEndtime))));
        if (MeetRoomTypeEnum.Company.equals(roomType)) {
            entity.setMeetroomid(ConvertUtil.convertToLong(dataMap.get(MeetManageEntity.FieldMeetroomid)));
            entity.setAirlinecompany(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldAirlinecompany)));
            entity.setAttendance(ConvertUtil.convertToInt(dataMap.get(MeetRoomApplyEntity.FieldAttendance)));
        } else if (MeetRoomTypeEnum.Remote.equals(roomType)) {
            entity.setMeetroomid(ConvertUtil.convertToLong(dataMap.get(MeetManageEntity.FieldRemoteroomid)));
            entity.setAirlinecompany(datacodeCache.getValueDynamic(MeetRoomManageEntity.tableName, String.valueOf(entity.getMeetroomid()), "id", "name"));
            entity.setAttendance(ConvertUtil.convertToInt(dataMap.get(MeetRoomTypeEnum.Remote+MeetRoomApplyEntity.FieldAttendance)));
        }
        // 来源类型和来源ID
        entity.setSourcetype(MeetManageEntity.tableName);
        entity.setSourceid(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldId)));
        // 其他信息
        entity.setEnabled(1);
        entity.setDeptcode(userBean.getDept().getCode());
        entity.setOrgcode(userBean.getOrg().getCode());
        entity.setUsercode(userBean.getUser().getCode());
        entity.setUsername(userBean.getUser().getName());
        entity.setTelephone(userBean.getUser().getMobile());
        // 得到参会人
        Map<String, Object> selectUsers = (Map<String, Object>) dataMap.get("selectUsers");
        List<Map<String, Object>> userList = this.basePermissionManageService.getAllAttendUser(selectUsers);
        List<String> userCodeList = new ArrayList<>();
        List<String> userNameList = new ArrayList<>();
        // 转会议室最大人数
        int maxPersons = ParameterCache.getIntValue("MeetMaxPersons", 50);
        for (Map<String, Object> map : userList) {
            userCodeList.add(ConvertUtil.convertToString(map.get("code")));
            userNameList.add(ConvertUtil.convertToString(map.get("name")));
            if (userCodeList.size() == maxPersons) {
                break;
            }
        }
        entity.setPartinnerusercode(String.join(",", userCodeList));
        entity.setPartinnerusername(String.join(",", userNameList));
        // 设置会务配置
        entity.setSourcelist(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldSourcelist)));
        entity.setOtherservice(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldOtherservice)));
        entity.setWelcomeinfo(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldWelcomeinfo)));
        entity.setWelcometime(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldWelcometime)));
        entity.setSigninfo(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldSigninfo)));
        entity.setTeainfo(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldTeainfo)));
        entity.setPreparerequest(ConvertUtil.convertToString(dataMap.get(MeetRoomApplyEntity.FieldPreparerequest)));
        return entity;
    }

    /**
     * 保存会议数据 生成会议室单据 保存人员记录
     *
     * @param dataMap
     * @param sessionUserBean
     * @description:
     * @author: donghang
     * @date: 2020年11月3日下午12:53:33
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MeetManageEntity save(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        MeetManageEntity meetManageEntity = new MeetManageEntity();
        meetManageEntity = (MeetManageEntity) meetManageEntity.convertFromMap(dataMap);
        //根据会议室线上线下形式 置空相反字段
        //并且限制旧会议选择线上，version为null则清空远程字段。
        handleRoomid(meetManageEntity);
        //进行初次创建id赋值及更新主单
        meetManageEntity = insertOrUpdateMeet(dataMap, meetManageEntity, sessionUserBean);
        //申请线下
        if (0L != meetManageEntity.getMeetroomid()) {
            // 生成会议室申请记录，删除原有记录并暂存新纪录
            this.deleteAndInsertRoomApply(MeetRoomTypeEnum.Company, dataMap, sessionUserBean);
        }
        //申请线上会议室
        if (0L != meetManageEntity.getRemoteroomid()) {
            //生成虚拟会议室申请
            this.deleteAndInsertRoomApply(MeetRoomTypeEnum.Remote, dataMap, sessionUserBean);
        }
        // 参会人员信息
        List<BasePermissionManageEntity> userList = new ArrayList<>();
        //如不选择参会人员，默认加入自己
        if (!dataMap.containsKey("selectUsers")) {// 默认参会人员是当前登录用户,主要适配手机用户
            Map<String, Object> defaultUser = new HashMap<>();
            defaultUser.put("usercodes", this.getSessionUserBean().getUser().getCode());
            defaultUser.put("usernames", this.getSessionUserBean().getUser().getName());
            dataMap.put("selectUsers", defaultUser);
        }
        Map<String, Object> selectUsers = (Map<String, Object>) dataMap.get("selectUsers");
        userList = this.basePermissionManageService.processSelectUsers(selectUsers, MeetPersonTypeEnum.Attend,
                sessionUserBean.getUser().getCode(), sessionUserBean.getUser().getName());

        basePermissionManageService.batchSaveList(String.valueOf(meetManageEntity.getId()), MeetManageEntity.tableName,
                userList);
        //进行参会人处理
        //生成人员记录  此处从会议发布初 挪到暂存中  方便记录历史
        self.handlePersonRecordChange(ConvertUtil.convertToString(meetManageEntity.getId()), selectUsers);
        // 提醒配置信息
        List<Map<String, Object>> remindList = null;
        if (dataMap.containsKey("remindList"))
            remindList = (List<Map<String, Object>>) dataMap.get("remindList");
        if (remindList != null) {
            this.baseRemindConfigService.batchSaveRemindConfigList(String.valueOf(meetManageEntity.getId()),
                    MeetManageEntity.tableName, remindList);
        }
        return meetManageEntity;
    }

    /**
     * 会议主单信息保存方法，新增插入，修改更新
     *
     * @return 更新后的会议entity
     * @author xinfushuo
     * @date 2023/3/30
     * @modify
     */
    @Transactional(rollbackFor = Exception.class)
    public MeetManageEntity insertOrUpdateMeet(Map<String, Object> dataMap, MeetManageEntity meetManageEntity, SessionUserBean sessionUserBean) {
        long id = ConvertUtil.convertToLong(dataMap.get("id"));
        if (ConvertUtil.convertToLong(dataMap.get(MeetManageEntity.FieldId)) == 0) {
            if (id <= 0) {// 赋值Id和单号
                long[] arrayId = PrimaryKeyUtil.GeneIDs(MeetManageEntity.tableName, 1);
                id = arrayId[0];
                meetManageEntity.setId(id);
                dataMap.put(MeetManageEntity.FieldId, id);
            }
            String docNo = String.valueOf(id);
            docNo = docNo.substring(0, 6) + docNo.substring(9);
            meetManageEntity.setMeetnum(docNo);
            meetManageEntity.setUsercode(sessionUserBean.getUser().getCode());
            meetManageEntity.setUsername(sessionUserBean.getUser().getName());
            meetManageEntity = this.insert(meetManageEntity);
        } else {
            this.updateEntity(meetManageEntity);
        }
        return meetManageEntity;
    }

    /**
     * 根据会议形式选择情况 清空字段信息 并设置远程会议信息
     *
     * @author xinfushuo
     * @date 2023/3/30
     * @modify
     */
    private void handleRoomid(MeetManageEntity entity) {
        if (MeetSystemConst.MeetStyle.Online.contentEquals(entity.getMeetstyle())) {
            //清空线下信息
            entity.setMeetroomid(0L);
            entity.setMeetroomtype("");
            entity.setAirlinecompany("");
            entity.setPlace("");
        } else if (MeetSystemConst.MeetStyle.Outline.contentEquals(entity.getMeetstyle())) {
            entity.setRemoteroomid(0L);
            entity.setRemotemeetinfo("");
        }
    }

    /**
     * @description: 会议暂存时，生成会议室申请记录，删除指定类型的的，保存新生成的
     * @author: chengengwei
     * @date: 2021-05-25
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public MeetRoomApplyEntity deleteAndInsertRoomApply(String roomType, Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        // 生成会议室申请记录，删除原有记录并暂存新纪录
        MeetRoomApplyEntity meetRoomApplyEntity = this.getMeetRoomApplyEntity(roomType, dataMap, sessionUserBean);
        StringBufferProxy whereSql = new StringBufferProxy();
        whereSql.appendSingle(" sourcetype = '{0}' and sourceid = {1}  and state in ('0','2')",
                MeetManageEntity.tableName, dataMap.get("id"));
        //删除指定类型的会议室申请
        whereSql.appendSingle("AND (SELECT TYPE FROM MEETROOMMANAGE ROOM  WHERE ROOM.ID = MEETROOMID) = '{0}'", roomType);
        this.meetRoomApplyService.deleteByWhere(whereSql.toString());
        whereSql.clear();
        this.meetRoomApplyService.insert(meetRoomApplyEntity);
        return meetRoomApplyEntity;
    }

    /**
     * 发布会议
     *
     * @param dataMap
     * @param sessionUserBean
     * @description:
     * @author: donghang
     * @date: 2020年11月3日上午9:19:34
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MeetManageEntity publishMeet(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        // 若dataMap带值为1的handlenextperoidtask参数，则是定时任务自动调用该发布方法，将下次周期会议置为发布状态，并进行会议室申请
        if (dataMap.containsKey("handlenextperoidtask") && "1".equals(dataMap.get("handlenextperoidtask"))) {
            return this.publishPeriodMeeting(dataMap, sessionUserBean);
        } else {
            //普通用戶发布会议
            return this.publishNormalMeeting(dataMap, sessionUserBean);
        }
    }

    /**
     * @param dataMap         发布会议信息 包含主单及消息提醒配置 参会人员等
     * @param sessionUserBean
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/14
     * @modify
     */
    public MeetManageEntity publishPeriodMeeting(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        // 判断会议室是否被占用，若被占用则发消息
        MeetRoomApplyEntity entity = this.getMeetRoomApplyEntity(MeetRoomTypeEnum.Company, dataMap, sessionUserBean);
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendLineSingle(" and state in (1,9) and meetroomid = {0} and begintime <{1} and endtime >{2} and id<>{3}",
                entity.getMeetroomid(),
                SQLAdapter.toDateLong(DateUtil.dateToString(entity.getEndtime(), "yyyy-MM-dd HH:mm:ss")),
                SQLAdapter.toDateLong(DateUtil.dateToString(entity.getBegintime(), "yyyy-MM-dd HH:mm:ss")),
                entity.getId());
        List<MeetRoomApplyEntity> meetRoomApplyEntities = meetRoomApplyService.queryByWhere(sql.toString());
        if (meetRoomApplyEntities.size() > 0) {
            // 设置为已提醒发起人更改周期会议
            dataMap.put(MeetManageEntity.FieldRemindchangeroom, BaseSystemConst.CboYesNoEnum.Yes);
            // 发送消息提醒
            List<BasicEntity> remindTaskList = new ArrayList<>();
            BaseRemindTaskEntity baseRemindTaskEntity = new BaseRemindTaskEntity();
            baseRemindTaskEntity.setUsercode(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldUsercode)));
            baseRemindTaskEntity.setUsername(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldUsername)));
            baseRemindTaskEntity.setSourceid(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldId)));
            baseRemindTaskEntity.setSourcetype(MeetManageEntity.tableName);
            baseRemindTaskEntity.setSourceaction(BaseSystemConst.BaseActionType.Remind);
            baseRemindTaskEntity.setRemindtime(new Date());
            baseRemindTaskEntity.setSubject(AppRemindTemplate.RemindChangePeroidMeetRoomSubjectTemplate);
            baseRemindTaskEntity.setNoticetype(NoticeTypeEnum.App);
            String content = String.format(AppRemindTemplate.RemindChangePeroidMeetRoomContentTemplate,
                    dataMap.get(MeetManageEntity.FieldName));
            baseRemindTaskEntity.setContent(content);
            remindTaskList.add(baseRemindTaskEntity);
            this.baseRemindTaskService.insertBatch(remindTaskList);
            //会议室冲突 赋值默认返回值
            return new MeetManageEntity();
        } else {
            // 更新发布状态
            dataMap.put(MeetManageEntity.FieldState, MeetStateEnum.Publish);
            this.meetRoomApplyService.apply(MeetRoomTypeEnum.Company, entity, sessionUserBean);
        }
        //获取会议权限信息
        StringBufferProxy permissionSql = new StringBufferProxy();
        permissionSql.appendSingle(" {0} = {1} ", BasePermissionManageEntity.FieldSourceid, dataMap.get(MeetManageEntity.FieldId));
        permissionSql.appendSingle(" AND {0} = '{1}'", BasePermissionManageEntity.FieldSourcetype, MeetManageEntity.tableName);
        //获取会议权限信息
        List<BasePermissionManageEntity> permissonList = this.basePermissionManageService.queryByWhere(permissionSql.toString());
        //消息配置
        List<Map<String,Object>> remindlist = this.baseRemindConfigService.queryMapByWhere(permissionSql.toString());
        Map<String,Object> selectUsers  = this.basePermissionManageService.processToMapUsers(permissonList);
        dataMap.put("selectUsers",selectUsers);
        //保存会议信息
        self.save(dataMap,sessionUserBean);
        generateMeetQRCode(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldMeetnum)), ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldId)));
        MeetManageEntity meetManageEntity = new MeetManageEntity();
        meetManageEntity.convertFromMap(dataMap);
        //对接日程
        this.doActualPublish(meetManageEntity, permissonList,remindlist,sessionUserBean,true);
        //首次发布生成历史
        this.publishHistoryCreate(meetManageEntity);
        return meetManageEntity;
    }

    /**
     * @param dataMap         发布会议信息 包含主单及消息提醒配置 参会人员等
     * @param sessionUserBean
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/14
     * @modify
     */
    public MeetManageEntity publishNormalMeeting(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        // 是否第一次发布，第一次发布需要发送新增消息提醒
        long id = ConvertUtil.convertToLong(dataMap.get("id"));
        boolean isFirstPublish = false;
        Map<String, Object> firstInfo = dataMap;
        int version = -1;
        if (id == 0) {
            version = 0;
            isFirstPublish = true;
        } else {
            MeetManageEntity meetManageEntity = this.queryById(ConvertUtil.convertToString(id));
            version = meetManageEntity.getVersion();
            firstInfo = meetManageEntity.convertToMap();
            if (meetManageEntity.getState() != MeetStateEnum.Publish && meetManageEntity.getState() != MeetStateEnum.Submit) {
                isFirstPublish = true;
            }
        }
        //如果不是第一次发布；大于等于0是限制历史数据
        if (!isFirstPublish && version >= 0) {
            //如果不是线下，且会议室
            if (!MeetSystemConst.MeetStyle.Outline.equals(ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldMeetstyle)))) {
                //有会议室版本号变化
                if (ConvertUtil.convertToLong(dataMap.get("remoteroomid")) > 0) {
                    //版本号加一
                    dataMap.put(MeetManageEntity.FieldVersion, version + 1);
                }
            }
        }
        // 1.更新发布状态
        dataMap.put(MeetManageEntity.FieldState, MeetStateEnum.Publish);
        // 进行会议主单暂存 及 会议室申请、人员记录生成
        MeetManageEntity meetManageEntity = self.save(dataMap, sessionUserBean);
        // 本次申请的线下会议室id
        String meetroomid = ConvertUtil.convertToString(meetManageEntity.getMeetroomid());
        // 本次申请的线上会议室id
        String remoteroomid = ConvertUtil.convertToString(meetManageEntity.getRemoteroomid());

        // 如果当前申请的会议室没有线上会议室，将以前申请的线上删除，后面有处理线下的代码
        if("0".equals(remoteroomid)){
            delRemoteRoom(meetManageEntity);
        }
        //  生成二维码
        if (isFirstPublish) {
            generateMeetQRCode(meetManageEntity.getMeetnum(), ConvertUtil.convertToString(meetManageEntity.getId()));
        }
        // 2.进行会议室申请
        //线下会议室申请
        applyMeetRoom(MeetRoomTypeEnum.Company, String.valueOf(meetManageEntity.getId()), sessionUserBean);
        //线上会议室申请
        applyMeetRoom(MeetRoomTypeEnum.Remote, String.valueOf(meetManageEntity.getId()), sessionUserBean);
        //若存在其他线上会议室申请，则先不进行 纪要新增更新、参会人变更 日程对接
        if (!queryHaveOtherRemoteRoom(meetManageEntity,remoteroomid)) {
            Map<String, Object> selectUsers = (Map<String, Object>) dataMap.get("selectUsers");
            List<BasePermissionManageEntity> permissionList = this.basePermissionManageService.processSelectUsers(
                    selectUsers, MeetPersonTypeEnum.Attend, sessionUserBean.getUser().getCode(), sessionUserBean.getUser().getName());
            this.doActualPublish(meetManageEntity, permissionList, (List<Map<String, Object>>) dataMap.get("remindList"), sessionUserBean, isFirstPublish);
        }
        if (version >= 0) {
            //第一次发布所有会议均生成历史
            if (isFirstPublish) {
                this.publishHistoryCreate(meetManageEntity);
            } else {
                MeetManageEntity meetManageUpdatedEntity = this.queryById(ConvertUtil.convertToString(meetManageEntity.getId()));
                //判断是否更新历史表数据，若是版本号没有变化，则进行history表更新
                if (ConvertUtil.convertToInt(firstInfo.get("version")) == meetManageUpdatedEntity.getVersion()) {
                    //获取要删除的历史版本
                    MeetManageHistoryEntity delHistory = meetManageHistoryService.queryObjectByWhere(" meetid="+meetManageUpdatedEntity.getId() +" and version="+meetManageUpdatedEntity.getVersion());
                    if (delHistory != null) {
                        //删除历史版本信息
                        meetManageHistoryService.deleteByWhere("id =" + delHistory.getId());
                        basePermissionManageHistoryService.deleteByWhere(" sourceid=" + delHistory.getId() +" and sourcetype='MeetManageHistory' ");
                        meetPersonRecordHistoryService.deleteByWhere(" meethistoryid=" + delHistory.getId());
                        baseRemindConfigHistoryService.deleteByWhere(" sourceid=" + delHistory.getId() +" and sourcetype='MeetManageHistory' ");
                        publishHistoryCreate(meetManageUpdatedEntity);
                    }
                }
            }
        }
        //删除无用审批流
        if (meetManageEntity.getMeetroomid() == 0) {
            Map<String, Object> outSelect = new HashMap<>();
            outSelect.put("meetid", meetManageEntity.getId());
            outSelect.put("roomtype", MeetRoomTypeEnum.Company);
            meetRoomApplyService.deleteUselessMeetRoomApply(outSelect);
        }
        if (meetManageEntity.getRemoteroomid() == 0) {
            Map<String, Object> outSelect = new HashMap<>();
            outSelect.put("meetid", meetManageEntity.getId());
            outSelect.put("roomtype", MeetRoomTypeEnum.Remote);
            meetRoomApplyService.deleteUselessMeetRoomApply(outSelect);
        }
        return meetManageEntity;
    }

    /**
     *  查询是否有除目前申请的线上会议室外是否还存在申请过其他线上会议室
     *
     * @param
     * @return
     * @throws
     * @author hudeyong
     * @date 2023/3/31
     * @modify
     */
    public boolean queryHaveOtherRemoteRoom(MeetManageEntity meetManageEntity, String remoteroomid) {
        // 如果本次申请不存在线上会议室，返回false
        if ("0".equals(remoteroomid)) {
            return false;
        }
        // 查询是否有除目前申请的线上会议室外是否还存在申请过其他线上会议室
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("SOURCEID = '{0}' and SOURCETYPE = '{1}' and MEETROOMID IN (SELECT id FROM MEETROOMMANAGE WHERE TYPE = '{2}') and state !=9 ",
                meetManageEntity.getId(), meetManageEntity.getTableName(), MeetRoomTypeEnum.Remote);
        List<MeetRoomApplyEntity> meetRoomApplyEntities = meetRoomApplyService.queryByWhere(sql.toString());
        //如果有，返回true，没有返回false
        if (meetRoomApplyEntities.size() > 0) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * @description: 第一次发布所有会议均生成历史
     * @return void
     * @author: wangxinhua
     * @date: 2023/4/3 11:28
     * @modify:
     */
    private void publishHistoryCreate(MeetManageEntity meetManageEntity) {
        StringBufferProxy sql = new StringBufferProxy();
        //大于等于0是限制历史数据,只有远程生成历史版本
        if (meetManageEntity != null && meetManageEntity.getVersion() >= 0) {
            MeetManageHistoryEntity meetManageHistoryEntity = new MeetManageHistoryEntity();
            BeanUtils.copyProperties(meetManageEntity, meetManageHistoryEntity);
            //设置默认值
            meetManageHistoryEntity.setMeetid(meetManageEntity.getId());
            meetManageHistoryEntity.setVersion(meetManageEntity.getVersion());
            //初始版本直接有效
            meetManageHistoryEntity.setValid(1);
            long[] arrayId = PrimaryKeyUtil.GeneIDs(meetManageHistoryEntity.getTableName(), 1);
            meetManageHistoryEntity.setId(arrayId[0]);
            meetManageHistoryService.insert(meetManageHistoryEntity);
            // 人员权限表
            List<BasicEntity> addEntities = new ArrayList<BasicEntity>();
            sql.appendSingle(" sourceid={0} ", meetManageEntity.getId());
            sql.appendSingle(" and sourcetype='{0}' ", MeetManageEntity.tableName);
            List<BasePermissionManageEntity> manageEntities = basePermissionManageService.queryByWhere(sql.toString());
            for (BasePermissionManageEntity item : manageEntities) {
                BasePermissionManageHistoryEntity historyEntity = new BasePermissionManageHistoryEntity();
                BeanUtils.copyProperties(item, historyEntity);
                historyEntity.setId(0L);
                historyEntity.setVersion(meetManageEntity.getVersion());
                historyEntity.setSourceid(ConvertUtil.convertToString(meetManageHistoryEntity.getId()));
                historyEntity.setSourcetype(MeetManageHistoryEntity.tableName);
                //保存会议管理id
                historyEntity.setBaseid(meetManageEntity.getId());
                addEntities.add(historyEntity);
            }
            if (addEntities.size() > 0) {
                basePermissionManageHistoryService.insertBatch(addEntities);
            }
            //保存人员记录历史表
            List<BasicEntity> addPersonEntities = new ArrayList<BasicEntity>();
            sql.clear();
            sql.appendSingle(" meetid={0} ", meetManageEntity.getId());
            List<MeetPersonRecordEntity> personRecordEntities = meetPersonRecordService.queryByWhere(sql.toString());
            for (MeetPersonRecordEntity pitem : personRecordEntities) {
                MeetPersonRecordHistoryEntity historyEntity = new MeetPersonRecordHistoryEntity();
                BeanUtils.copyProperties(pitem, historyEntity);
                historyEntity.setId(0L);
                historyEntity.setVersion(meetManageEntity.getVersion());
                //保存会议管理id
                historyEntity.setMeethistoryid(meetManageHistoryEntity.getId());
                addPersonEntities.add(historyEntity);
            }
            if (addPersonEntities.size() > 0) {
                meetPersonRecordHistoryService.insertBatch(addPersonEntities);
            }
            //存信息配置
            List<BasicEntity> addRemindEntities = new ArrayList<BasicEntity>();
            sql.clear();
            sql.appendSingle(" sourceid={0} ", meetManageEntity.getId());
            sql.appendSingle(" and sourcetype='{0}' ", MeetManageEntity.tableName);
            List<BaseRemindConfigEntity> remindEntities = baseRemindConfigService.queryByWhere(sql.toString());
            for (BaseRemindConfigEntity ritem : remindEntities) {
                BaseRemindConfigHistoryEntity historyEntity = new BaseRemindConfigHistoryEntity();
                BeanUtils.copyProperties(ritem, historyEntity);
                historyEntity.setId(0L);
                historyEntity.setSourceid(ConvertUtil.convertToString(meetManageHistoryEntity.getId()));
                historyEntity.setSourcetype(MeetManageHistoryEntity.tableName);
                //保存会议管理id
                historyEntity.setMeetid(meetManageEntity.getId());
                addRemindEntities.add(historyEntity);
            }
            if (addRemindEntities.size() > 0) {
                baseRemindConfigHistoryService.insertBatch(addRemindEntities);
            }
        }
    }

    public void delRemoteRoom(MeetManageEntity meetManageEntity) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("SOURCEID = '{0}' AND SOURCETYPE  = 'MeetManage' AND MEETROOMID IN (SELECT id FROM MEETROOMMANAGE WHERE TYPE = '{1}')",
                meetManageEntity.getId(),MeetRoomTypeEnum.Remote);
        List<MeetRoomApplyEntity> roomApplyEntities = meetRoomApplyService.queryByWhere(sql.toString());
        for (MeetRoomApplyEntity roomApplyEntity : roomApplyEntities) {
            String id = ConvertUtil.convertToString(roomApplyEntity.getId());
            meetRoomApplyService.executeDelApprove(id, this.getSessionUserBean());
            meetRoomApplyService.deleteById(id);
        }
    }
    /**
     * 实际发布逻辑 创建更新会议纪要  参会人进行变更  工作日程进行对接  新增 修改
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2023/3/31
     * @modify
     */
    @Override
    public void doActualPublish(MeetManageEntity meetManageEntity, List<BasePermissionManageEntity> permissionList, List<Map<String, Object>> remindList, SessionUserBean sessionUserBean, boolean isFirstPublish) {
        // 3.会议纪要创建或者更新
        this.createRecordByMeet(meetManageEntity, this.isInsertMeetRecord(ConvertUtil.convertToString(meetManageEntity.getId())));
        // 6.对接工作日程
        this.submitWorkSchedule(meetManageEntity, remindList, permissionList,
                true, isFirstPublish);
    }

    /**
     * 会议信息进行发布
     *
     * @return
     * @author xinfushuo
     * @date 2023/3/31
     * @modify
     */
    @Override
    public void publishAfterApproval(MeetManageEntity meetManageEntity) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("sourcetype = '{0}' and sourceid = '{1}' ", MeetManageEntity.tableName, meetManageEntity.getId());
        List<BasePermissionManageEntity> permissionList = basePermissionManageService.queryByWhere(sql.toString());
        List<Map<String, Object>> remindConfigList = baseRemindConfigService.queryMapByWhere(sql.toString());
        remindConfigList.forEach(map -> map.remove(BaseRemindConfigEntity.FieldState));
        //若当前会议在发布变更中 则不是第一次发布
        boolean isFirstPublish = MeetStateEnum.SubmitChange!= meetManageEntity.getState();
        self.doActualPublish(meetManageEntity,permissionList,remindConfigList,this.getSessionUserBean(),isFirstPublish);
    }

    /**
     * @param roomType 会议室类型
     * @param meetid   会议id
     * @return
     * @throws
     * @author xinfushuo
     * @date 2023/3/30
     * @modify
     */
    private void applyMeetRoom(String roomType, String meetid, SessionUserBean userBean) {
        List<MeetRoomApplyEntity> meetRoomApplyEntities = queryMeetRoomApply(roomType, meetid, "");
        if (!meetRoomApplyEntities.isEmpty()) {
            for (MeetRoomApplyEntity applyEntity : meetRoomApplyEntities) {
                if (applyEntity.getState() == 0) {
                    this.meetRoomApplyService.apply(roomType, applyEntity, userBean);
                    break;
                }
            }
        }
    }

    /**
     * 查询会议室
     *
     * @param roomType 会议室类型
     * @param meetid   会议id
     * @author xinfushuo
     * @date 2023/3/30
     * @modify
     */
    private List<MeetRoomApplyEntity> queryMeetRoomApply(String roomType, String meetid, String approvalState) {
        StringBufferProxy whereSql = new StringBufferProxy();
        whereSql.appendSingle(" sourcetype = '{0}' and sourceid = {1} ",
                MeetManageEntity.tableName, meetid);
        whereSql.appendSingle("AND (SELECT TYPE FROM MEETROOMMANAGE ROOM  WHERE ROOM.ID = MEETROOMID) = '{0}'", roomType);
        if (!approvalState.isEmpty()) {
            whereSql.appendSingle("AND STATE = '{0}' ", approvalState);
        }
        return this.meetRoomApplyService.queryByWhere(whereSql.toString());
    }

    /**
     * 处理会议系统 重新发布的参会人员记录变更
     *
     * @param meetId      会议id
     * @param selectUsers 团队 人员 部门聚合参会人数据
     * @throws
     * @author xinfushuo
     * @date 2022/9/14
     * @modify
     */
    @Transactional(rollbackFor = Exception.class)
    public void handlePersonRecordChange(String meetId, Map<String, Object> selectUsers) {
        // 将参会人员插入人员记录表
        List<Map<String, Object>> userList = this.basePermissionManageService.getAllAttendUser(selectUsers);
        List<Map<String, Object>> existPersonRecordList = this.getPersonRecordListByMeetId(meetId);
        // 得到画面选中的比数据库中多的数据，用于插入
        List<Map<String, Object>> insertList = getExtraRecords(userList, existPersonRecordList,
                CboUserEntity.FieldCode);
        // 得到数据库中比画面选中的多的记录，用于删除
        List<Map<String, Object>> deleteList = getExtraRecords(existPersonRecordList, userList,
                MeetPersonRecordEntity.FieldUsercode);
        // 删除记录
        this.deletePersonRecords(deleteList);
        // 插入记录
        this.meetPersonRecordService.insertDataList(meetId, insertList);
    }

    /**
     * 取消会议
     *
     * @param dataMap
     * @param sessionUserBean
     * @description:
     * @author: donghang
     * @date: 2020年11月3日上午9:19:42
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelMeet(Map<String, Object> dataMap, SessionUserBean sessionUserBean) {
        // 1.更新取消状态
        dataMap.put(MeetManageEntity.FieldState, MeetStateEnum.Cancel);
        this.update(dataMap);
        String meetId = ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldId));
        // 2.会议室申请撤销
        if (this.isApplyMeetRoom(dataMap)) {
            this.meetRoomApplyService.cancel(MeetManageEntity.tableName, meetId, sessionUserBean);
        }
        // 3、会议纪要删除
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and meetid = '{0}'", meetId);
        this.meetRecordService.deleteByWhere(sql.toString());
        // 4.日程撤销
        this.workScheduleService.cancelWorkSchedule(WorkSourceAppEnum.Meet, MeetManageEntity.tableName, meetId);
        // 5.删除历史版本信息
        meetManageHistoryService.deleteByWhere(MeetManageHistoryEntity.FieldMeetid+" = " + meetId);
        basePermissionManageHistoryService.deleteByWhere(" baseid=" + meetId);
        meetPersonRecordHistoryService.deleteByWhere(" meetid=" + meetId);
        baseRemindConfigHistoryService.deleteByWhere(" meetid=" + meetId);
    }

    /**
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/7Z
     * @modify
     */
    @Override
    public void stopSign(String meetid, SessionUserBean userBean) {

        beforeStopSign(meetid, userBean);
        Map<String, Object> updateMap = new HashMap<>();
        List<String> fieldList = Arrays.asList(MeetManageEntity.FieldId, MeetManageEntity.FieldSignstate);
        updateMap.put(MeetManageEntity.FieldId, meetid);
        updateMap.put(MeetManageEntity.FieldSignstate, BaseSystemConst.CboYesNoEnum.No);
        self.update(updateMap);
    }

    /**
     * 停止签到之前进行校验
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/7
     * @modify
     */
    private void beforeStopSign(String meetid, SessionUserBean userBean) {
        if (StrUtil.isEmpty(meetid)) {
            throw new ServiceException("找不到对应会议！");
        }
        MeetManageEntity meetManageEntity = this.queryById(meetid);
        String usercode = meetManageEntity.getUsercode();
        String lauchUserCode = meetManageEntity.getLaunchusercode();
        String sourceapp = meetManageEntity.getSourceapp();
        if (!MeetSystemConst.MeetSourceAppEnum.MPM.contentEquals(sourceapp)) {
            throw new ServiceException("只有来源为销售项目的会议可以停止签到！");
        }
        if (!userBean.getUser().getCode().contentEquals(usercode) && !userBean.getUser().getCode().contentEquals(lauchUserCode)) {
            throw new ServiceException("您不是该会议发起人，无法进行该操作。");
        }
    }

    /**
     * 提交日程
     *
     * @param meetManageEntity
     * @description:
     * @author: donghang
     * @date: 2020年11月5日下午5:38:44
     * @modify:
     */
    @Override
    public void submitWorkSchedule(MeetManageEntity meetManageEntity, List<Map<String, Object>> remindList,
                                   List<BasePermissionManageEntity> permissionList, boolean isSendMessage, boolean isFirstPublish) {
        WorkScheduleEntity workScheduleEntity = new WorkScheduleEntity();
        workScheduleEntity.setBegintime(meetManageEntity.getBegintime());
        workScheduleEntity.setEndtime(meetManageEntity.getEndtime());
        workScheduleEntity.setScheduletype(WorkSourceTypeEnum.MeetType);
        workScheduleEntity.setName(meetManageEntity.getName());
        workScheduleEntity.setContent(meetManageEntity.getContent());
        workScheduleEntity.setSourceapp(WorkSourceAppEnum.Meet);
        workScheduleEntity.setSourceid(ConvertUtil.convertToString(meetManageEntity.getId()));
        workScheduleEntity.setSourcetype(MeetManageEntity.tableName);
        workScheduleEntity.setHandleusercode(WorkHandleUserEnum.MeetHandleUsercode);
        // 判断自定义地点是否为空，若为空则取会议室名称
        if (!StringUtil.isEmpty(meetManageEntity.getAirlinecompany())) {
            workScheduleEntity.setPlace(meetManageEntity.getAirlinecompany());
        } else {
            workScheduleEntity.setPlace(meetManageEntity.getPlace());
        }
        // 查询人员部门信息
        StringBufferProxy queryFromUserSql = new StringBufferProxy();
        queryFromUserSql.appendSingle("code in ('{0}')", meetManageEntity.getUsercode());
        List<CboUserEntity> cboUserEntityFromList = this.cboUserService.queryByWhere(queryFromUserSql.toString());
        if (cboUserEntityFromList.size() == 1) {
            // 获取部门描述
            CboDeptEntity cboDeptEntity = this.cbodeptservice
                    .queryObjectByWhere("id in ('" + cboUserEntityFromList.get(0).getDeptid() + "')");
            workScheduleEntity.setHandleusername(cboDeptEntity.getFullname() + "\\" + meetManageEntity.getUsername());
        } else {
            workScheduleEntity.setHandleusername(meetManageEntity.getUsername());
        }

        workScheduleEntity.setTags(meetManageEntity.getKeywords());
        List<BaseRemindConfigEntity> remindEntityList = new ArrayList<>();
        if (remindList != null) {
            for (Map<String, Object> map : remindList) {
                BaseRemindConfigEntity baseRemindConfigEntity = new BaseRemindConfigEntity();
                baseRemindConfigEntity = (BaseRemindConfigEntity) baseRemindConfigEntity.convertFromMap(map);
                baseRemindConfigEntity.setId(0);
                remindEntityList.add(baseRemindConfigEntity);
            }
        }
        if (permissionList != null) {
            for (BasePermissionManageEntity basePermissionManageEntity : permissionList) {
                basePermissionManageEntity.setId(0);
            }
        }
        // 日程对接
        this.workScheduleService.submitWorkSchedule(workScheduleEntity, permissionList, remindEntityList, isSendMessage,
                isFirstPublish);
    }

    /**
     * @param meetId
     * @return
     * @description: 通过会议Id查询已经发布的参会人员
     * @author: wanghongwei
     * @date: 2020-11-4 16:26:43
     * @modify:
     */
    private List<Map<String, Object>> getPersonRecordListByMeetId(String meetId) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and meetid = '{0}'", meetId);
        return this.meetPersonRecordService.queryMapByWhere(sql.toString());
    }

    /**
     * @param newList
     * @param oldList
     * @param newKey
     * @return
     * @description: 比较两个list，按照Key对应的value值得到新list比旧list多的记录
     * @author: wanghongwei
     * @date: 2020-11-4 18:09:19
     * @modify:
     */
    private List<Map<String, Object>> getExtraRecords(List<Map<String, Object>> newList,
                                                      List<Map<String, Object>> oldList, String newKey) {
        List<Map<String, Object>> extraData = new ArrayList<>();
        for (Map<String, Object> newMap : newList) {
            boolean isContain = false;
            for (Map<String, Object> oldMap : oldList) {
                String newValue = ConvertUtil.convertToString(newMap.get(newKey));
                if (oldMap.containsValue(newValue)) {
                    isContain = true;
                    break;
                }
            }
            if (!isContain) {
                extraData.add(newMap);
            }
        }
        return extraData;
    }

    /**
     * @param deleteList
     * @description: 删除人员记录信息
     * @author: wanghongwei
     * @date: 2020-11-4 18:02:16
     * @modify:
     */
    private void deletePersonRecords(List<Map<String, Object>> deleteList) {
        StringBufferProxy ids = new StringBufferProxy();
        int count = 0;
        for (Map<String, Object> map : deleteList) {
            ids.appendSingle(ConvertUtil.convertToString(map.get(MeetPersonRecordEntity.FieldId) + ","));
            count++;
            if (count % 1000 == 0) {
                ids = ids.substring(0, ids.length() - 1);
                this.meetPersonRecordService.deleteByIds(ids.toString());
                ids.clear();
            }
        }
        if (ids.length() > 0) {
            ids = ids.substring(0, ids.length() - 1);
            this.meetPersonRecordService.deleteByIds(ids.toString());
        }
    }

    /**
     * @param id
     * @description: 是否插入会议纪要
     * @author: wanghongwei
     * @date: 2020-11-11 17:19:17
     * @modify:
     */
    private boolean isInsertMeetRecord(String id) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and meetid = '{0}'", id);
        return this.meetRecordService.queryByWhere(sql.toString()).size() == 0;
    }

    /**
     * @param meetManageEntity
     * @param isAdd
     * @return
     * @description: 通过会议创建或者更新会议纪要
     * @author: wanghongwei
     * @date: 2020-11-11 17:16:04
     * @modify:
     */
    @Override
    public MeetRecordEntity createRecordByMeet(MeetManageEntity meetManageEntity, boolean isAdd) {
        MeetRecordEntity meetRecordEntity = new MeetRecordEntity();
        meetRecordEntity.setMeetid(meetManageEntity.getId());
        meetRecordEntity.setAirlinecompany(meetManageEntity.getAirlinecompany());
        meetRecordEntity.setBegintime(meetManageEntity.getBegintime());
        meetRecordEntity.setEndtime(meetManageEntity.getEndtime());
        meetRecordEntity.setContent(meetManageEntity.getContent());
        meetRecordEntity.setKeywords(meetManageEntity.getKeywords());
        meetRecordEntity.setLaunchorgindex(meetManageEntity.getLaunchorgindex());
        meetRecordEntity.setLaunchorgname(meetManageEntity.getLaunchorgname());
        meetRecordEntity.setLaunchorgtype(meetManageEntity.getLaunchorgtype());
        meetRecordEntity.setLaunchusercode(meetManageEntity.getLaunchusercode());
        meetRecordEntity.setLaunchusername(meetManageEntity.getLaunchusername());
        meetRecordEntity.setManageusercodes(meetManageEntity.getManageusercodes());
        meetRecordEntity.setManageusernames(meetManageEntity.getManageusernames());
        meetRecordEntity.setMeetnum(meetManageEntity.getMeetnum());
        meetRecordEntity.setMeetroomid(meetManageEntity.getMeetroomid());
        meetRecordEntity.setMeetroomtype(meetManageEntity.getMeetroomtype());
        meetRecordEntity.setName(meetManageEntity.getName());
        meetRecordEntity.setPlace(meetManageEntity.getPlace());
        meetRecordEntity.setUsercode(meetManageEntity.getUsercode());
        meetRecordEntity.setUsername(meetManageEntity.getUsername());
        meetRecordEntity.setMeettypeid(meetManageEntity.getMeettypeid());
        meetRecordEntity.setMeetstyle(meetManageEntity.getMeetstyle());
        if (isAdd) {
            meetRecordEntity = this.meetRecordService.insert(meetRecordEntity);
            // 设置默认录音、纪要权限
            this.setRecordDefaultUser(meetManageEntity, ConvertUtil.convertToString(meetRecordEntity.getId()));
        } else {
            this.meetRecordService.updateByWhere(meetRecordEntity.convertToMap(),
                    "meetnum='" + meetManageEntity.getMeetnum() + "'");
        }
        return meetRecordEntity;
    }

    /**
     * @param meetManageEntity
     * @description:
     * @author: donghang
     * @date: 2020年11月25日下午11:44:58
     * @modify:
     */
    private void setRecordDefaultUser(MeetManageEntity meetManageEntity, String recordId) {
        //wtf is this ? 为啥 周期任务创建会议才会设置默认范围?
        if (meetManageEntity.getPeroidtaskid() == 0) {
            return;
        }
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("qry_peroidtaskid", meetManageEntity.getPeroidtaskid());
        List<Map<String, Object>> recordList = this.meetRecordService.queryMap(queryMap, "queryRecentlyRecordPeroid");
        if (recordList.size() == 1) {
            String recentlyRecordId = ConvertUtil.convertToString(recordList.get(0).get("id"));
            // 得到纪要默认录音、纪要权限
            StringBufferProxy sql = new StringBufferProxy();
            sql.appendSingle(" 1=1 ");
            sql.appendSingle(" and sourceid = '{0}' and sourcetype='{1}' and sourceflag in ('{2}','{3}') ",
                    recentlyRecordId, MeetRecordEntity.tableName, MeetPersonTypeEnum.Record, MeetPersonTypeEnum.Audio);
            List<BasePermissionManageEntity> permissionList = this.basePermissionManageService
                    .queryByWhere(sql.toString());
            for (BasePermissionManageEntity basePermissionManageEntity : permissionList) {
                basePermissionManageEntity.setSourceid(recordId);
                basePermissionManageEntity.setId(0);
                this.basePermissionManageService.insert(basePermissionManageEntity);
            }
        }

    }

    /**
     * 发送会议确认消息
     *
     * @description: 发送会议确认消息 并进行会议自动发布
     * @author: donghang
     * @date: 2020年11月10日下午6:14:39
     * @modify: chengengwei
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendSubmitMessages() {
        // 查询在当前时间内的消息
        String currentDate = DateUtil.dateToString(new Date(), "yyyy-MM-dd");
        StringBufferProxy sql = new StringBufferProxy();
        // 查询当天的需要待确认的会议
        log.info("查询当天的需要待确认的周期会议");
        sql.appendSingle("1=1");
        sql.appendLineSingle(" and advancesubmittime>={0} and advancesubmittime<={1} and state='{2}' and {3} ='{4}'",
                SQLAdapter.toDateLong(currentDate + " 00:00:00"), SQLAdapter.getDate(), MeetStateEnum.Wait, MeetManageEntity.FieldRemindchangeroom, BaseSystemConst.CboYesNoEnum.No);
        List<MeetManageEntity> meetList = this.queryByWhere(sql.toString());
        List<BasicEntity> remindTaskList = new ArrayList<>();
        //处理待确认会议
        for (MeetManageEntity meet : meetList) {
            String createUserCode = ConvertUtil.convertToString(meet.getUsercode());
            //发送待确认消息
            if (ConvertUtil.convertToString(meet.getUsercode()).length() > 0) {
                //获取当前会议发布人usercode 及 设置ThreadLocal SessionUserBean
                SessionUserBean sessionUserBean = this.getBeanByUserCode(meet.getUsercode());
                ThreadLocalContext.sessionUserBeanThreadLocal.set(sessionUserBean);
                //发送会议确认提醒
                log.info("组装并插入会议确认消息");
                remindTaskList.add(this.sendPeriodMeetConfirmMessage(meet));
                Map<String, Object> meetPublishMap = meet.convertToMap();
                meetPublishMap.put("handlenextperoidtask", "1");
                //进行会议发布提醒  日后改为消息提醒中确认
                log.info("进行周期会议发布");
                publishMeet(meetPublishMap, sessionUserBean);
            }
        }
        this.baseRemindTaskService.insertBatch(remindTaskList);
// 获取开始时间在今天0点到现在的状态为3的周期会议记录，手动拼接参数并进行发布
//		Map<String, Object> paramMap = new HashMap<>();
//		paramMap.put("begintime", currentDate + " 00:00:00");
//		List<Map<String, Object>> selectNextPeroidTaskList = this.queryMap(paramMap, "selectNextPeroidTask");
//		selectNextPeroidTaskList.forEach(task -> {
//			// 添加handleNextPeroidTask参数，为了区分是用户自己发布的还是系统自动发布的
//			task.put("handlenextperoidtask", "1");
//			// 基础权限表中人员配置已经添加过，日程也生成过，因此不需要selectUsers、remindList
//			// 查询会议创建人，拼接sessionUserBean
//			SessionUserBean sessionUserBean = this.getBeanByUserCode(ConvertUtil.convertToString(task.get("usercode")));
//			ThreadLocalContext.sessionUserBeanThreadLocal.set(sessionUserBean);
//			publishMeet(task, sessionUserBean);
//		});
    }

    /**
     * @param meet 会议实体
     * @return BaseRemindTaskEntity 周期会议提醒remindtask
     * @description: 组装会议确认消息并
     * @author xinfushuo
     * @date 2022/8/19
     * @modify
     */
    private BaseRemindTaskEntity sendPeriodMeetConfirmMessage(MeetManageEntity meet) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("1=1");
        sql.appendLineSingle(" and sourceid='{0}' and sourcetype='{1}'",
                ConvertUtil.convertToString(meet.getId()), MeetManageEntity.tableName);
        this.baseRemindTaskService.deleteByWhere(sql.toString());
        // 增加新发送
        BaseRemindTaskEntity baseRemindTaskEntity = new BaseRemindTaskEntity();
        baseRemindTaskEntity.setUsercode(meet.getUsercode());
        baseRemindTaskEntity.setUsername(ConvertUtil.convertToString(meet.getUsername()));
        baseRemindTaskEntity.setSourceid(ConvertUtil.convertToString(meet.getId()));
        baseRemindTaskEntity.setSourcetype(MeetManageEntity.tableName);
        baseRemindTaskEntity.setSourceaction(BaseSystemConst.BaseActionType.Remind);
        // 立即发送
        baseRemindTaskEntity.setRemindtime(
                DateUtil.addDate(ConvertUtil.convertToDate(meet.getAdvancesubmittime()),
                        0, Calendar.MINUTE));
        baseRemindTaskEntity.setSubject(BaseRemindTemplate.AppRemindTemplate.AppMeetSubmitSubjectTemplate);
        baseRemindTaskEntity.setNoticetype(NoticeTypeEnum.App);
        Date meetBeginTime = ConvertUtil.convertToDate(meet.getBegintime());
        String content = String.format(AppRemindTemplate.RemindPeroidMeetContentTemplate,
                DateUtil.dateToString(meetBeginTime, "MM-dd HH:mm"),
                meet.getName());
        baseRemindTaskEntity.setContent(content);
        return baseRemindTaskEntity;
    }

    /**
     * @param usercode
     * @return SessionUserbean
     * @throws
     * @description: 根据用户名获取SessionUserbean
     * @author xinfushuo
     * @date 2022/8/19
     * @modify
     */
    private SessionUserBean getBeanByUserCode(String usercode) {
        SecurityUserDetails userDetails = (SecurityUserDetails) userDetailsService.loadUserByUsername(usercode);
        SessionUserBean sessionUserBean = new SessionUserBean();
        sessionUserBean.setUser(userDetails.getUser());
        sessionUserBean.setOrg(userDetails.getOrg());
        sessionUserBean.setWorkOrg(userDetails.getWorkOrg());
        sessionUserBean.setDept(userDetails.getDept());
        sessionUserBean.setWorkDept(userDetails.getWorkDept());
        sessionUserBean.setRoleList(userDetails.getRoleList());
        return sessionUserBean;
    }

    /**
     * @param mapRow
     * @param datacodeCache
     * @description:
     * @author: donghang
     * @date: 2020年11月9日上午9:12:16
     * @modify:
     */
    @Override
    public void setDispFields(Map<String, Object> mapRow, DatacodeCache datacodeCache) {
        super.setDispFields(mapRow, datacodeCache);
        String temp;
        //todo 优化此处代码 使用Redis缓存查询join的方法进行
        if (mapRow.get("meettypeid") != null) {
            temp = mapRow.get("meettypeid").toString();
            String name = "", parentName = "";
            List<MeetTypeManageEntity> meetList = this.meetTypeManageService.queryByWhere("id=" + temp);
            if (meetList.size() == 1) {
                name = meetList.get(0).getName();
                if (meetList.get(0).getParentid() > 0) {
                    List<MeetTypeManageEntity> parentList = this.meetTypeManageService
                            .queryByWhere("id=" + meetList.get(0).getParentid());
                    if (parentList.size() == 1) {
                        parentName = parentList.get(0).getName();
                    }
                }
            }
            if (parentName.length() > 0) {
                mapRow.put("dispmeettypeid", parentName + "/" + name);
            } else {
                mapRow.put("dispmeettypeid", name);
            }

        }
    }

    /**
     * @description: 对会议列表记录添加会议录音、会议纪要等会议状态
     * @author: chengengwei
     * @date: 2021-2-23
     * @modify:
     */
    @Override
    public void addMeetState(List<Map<String, Object>> tempList) {
        if (tempList.size() > 0) {
            // 会议号meetnum拼接
            List<String> meetnumsList = tempList.stream().map(map -> ConvertUtil.convertToString(map
                    .get(MeetManageEntity.FieldMeetnum))).collect(Collectors.toList());
            String meetnums = meetnumsList.stream().collect(Collectors.joining("','"));
            meetnums = "'" + meetnums + "'";
            Map<String, Object> tempParamMap = new HashMap<>();
            tempParamMap.put("sourcetype", "meetRecord");
//            tempParamMap.put("meetnums", meetnums);
            tempParamMap.put("meetnumlist", meetnumsList);
            // 各个会议录音文件记录
            List<Map<String, Object>> fileManageList = fileManageService.queryMap(tempParamMap, "queryFileNum");
            // key为会议号meetnum，value为对应录音文件数
            Map<String, Integer> fileManageMap = fileManageList.stream().collect(Collectors.toMap(map -> ConvertUtil
                    .convertToString(map.get("meetnum")), map -> ConvertUtil.convertToInt(map.get("totalnum"))));

            StringBufferProxy tempSql = new StringBufferProxy();
            // 查询每个会议对应的会议纪要数
            List<Map<String, Object>> recordList = cboAttachmentService.queryMap(tempParamMap, "queryMeetAttachment");
            // key为会议号meetnum，value为对应会议纪要数
            Map<String, Integer> recordMap = recordList.stream().collect(Collectors.toMap(map -> ConvertUtil
                    .convertToString(map.get("meetnum")), map -> ConvertUtil.convertToInt(map.get("totalnum"))));

            // 调用OA接口得到任务下发状态和任务完成状态
            Map<String, Object> paraOA = new HashMap<>();
            paraOA.put("sourcesys", MeetSystemConst.OATaskSourceInfo.Sourcesys);
            paraOA.put("sourcemoudule", MeetSystemConst.OATaskSourceInfo.Sourcemodule);
            paraOA.put("sourceids", meetnumsList.stream().collect(Collectors.joining(",")));
            String paraOAStr = JSON.toJSONString(paraOA);
            String oaResultJson = "";
            try {
                oaResultJson = smsWorkTasksCloseService.queryTaskStateFromMeet(paraOAStr);
            } catch (Exception e) {
                log.error(e.getMessage());
                return;
            }
            OAResult<JSONArray> oaResult = JSON.parseObject(oaResultJson, OAResult.class);
            if (!oaResult.getSuccess()) {
                log.error("查询OA系统任务列表失败");
                return;
            }
            JSONArray jsonData = oaResult.getData();
            List<Map> stateList = JSONObject.parseArray(jsonData.toJSONString(), Map.class);
            //key为会议号meetnum，value为对应会议是否下发任务
            Map<String, Boolean> taskIssuedMap = stateList.stream().collect(Collectors.toMap(map -> ConvertUtil
                    .convertToString(map.get("id")), map -> ConvertUtil.convertToBoolean(map.get("taskissued"))));
            // key为会议号meetnum，value为对应会议是否已完成所有任务
            Map<String, Boolean> taskCompletedMap = stateList.stream().collect(Collectors.toMap(map -> ConvertUtil
                    .convertToString(map.get("id")), map -> ConvertUtil.convertToBoolean(map.get("taskcompleted"))));

            tempList.forEach(map -> {
                // 若录音文件数大于0则为true
                String meetnum = ConvertUtil.convertToString(map.get("meetnum"));
                if (fileManageMap.keySet().contains(meetnum) && fileManageMap.get(meetnum) > 0) {
                    map.put("audioUploaded", true);
                } else {
                    map.put("audioUploaded", false);
                }
                // 若会议纪要数大于0则为true
                if (recordMap.keySet().contains(meetnum) && recordMap.get(meetnum) > 0) {
                    map.put("recordUploaded", true);
                } else {
                    map.put("recordUploaded", false);
                }
                // 若任务数大于0则为true
                map.put("taskissued", taskIssuedMap.get(meetnum));
                map.put("taskcompleted", taskCompletedMap.get(meetnum));
                // 计算会议时长
                Date begintime = ConvertUtil.convertToDate(map.get("begintime"));
                Date endtime = ConvertUtil.convertToDate(map.get("endtime"));
                if (begintime != null && endtime != null) {
                    Long interval = endtime.getTime() - begintime.getTime();
                    Long intervalHour = interval / (3600 * 1000);
                    Long intervalMinute = (interval % (3600 * 1000)) / (60 * 1000);
                    map.put("interval", intervalHour + "小时" + (intervalMinute > 0 ? intervalMinute + "分钟" : ""));
                } else {
                    map.put("interval", "");
                }
            });
        }
    }

    /**
     * @description: 提醒上传会议纪要
     * @author: chengengwei
     * @date: 2021-2-23
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remindUploadRecord() {
        // 会议结束后多长时间开始提醒上传会议纪要
        double afterMeetTime = ConvertUtil.convertToDouble(ParameterCache
                .getValue(MeetSystemConst.ReminUploadRecordTime, "72"));
        // 最短每隔多长时间提醒一次
        double intervalTime = ConvertUtil.convertToDouble(ParameterCache
                .getValue(MeetSystemConst.ReminUploadRecordInterval, "24"));
        Date now = new Date();
        // 当前时间 - afterMeetTime，只需要提醒结束时间小于该时间的会议
        DateTime latestEndTime = cn.hutool.core.date.DateUtil.offsetMinute(now, (int) (afterMeetTime * 60 * -1));
        // 当前时间 - 间隔时间，上次提醒时间小于该结果的都需要提醒
        DateTime latestRemindTime = cn.hutool.core.date.DateUtil.offsetMinute(now, (int) (intervalTime * 60 * -1));
        StringBufferProxy whereSql = new StringBufferProxy();
        // 判断是否发送消息条件：1.状态为发布。2.未上传会议纪要。3.latestEndTime大于会议结束时间。4.latestRemindTime大于上次提醒时间。5.来源类型为空。即非其它系统集成创建的会议
        whereSql.appendSingle(" state = {0} and ( recorduploaded != {1} or recorduploaded is null ) and {2} >= endtime" +
                        " and ( remindrecordlasttime is null or {3} >= remindrecordlasttime ) ",
                MeetStateEnum.Publish, BaseSystemConst.CboYesNoEnum.Yes,
                SQLAdapter.toDateLong(cn.hutool.core.date.DateUtil.formatDateTime(latestEndTime)),
                SQLAdapter.toDateLong(cn.hutool.core.date.DateUtil.formatDateTime(latestRemindTime)));
        whereSql.appendSingle(" and ( sourcetype is null or sourcetype = '' ) ");
        List<Map<String, Object>> meetManageList = this.queryMapByWhere(whereSql.toString());
        whereSql.clear();
        if (meetManageList.size() > 0) {
            // 消息列表
            List<BasicEntity> pushList = new ArrayList<>();
            // 消息主题
            String subject = AppRemindTemplate.RemindUploadRecordSubjectTemplate;
            for (Map<String, Object> map : meetManageList) {
                // 更新提醒时间字段
                map.put(MeetManageEntity.FieldRemindrecordlasttime, now);
                // 发送消息，若有会议秘书则只发会议秘书，否则发会议创建人
                String usercode = ConvertUtil.convertToString(map.get(MeetManageEntity.FieldUsercode));
                String manageUserCodes = ConvertUtil.convertToString(map.get(MeetManageEntity.FieldManageusercodes));
                String notRemindUserCodes = ConvertUtil.convertToString(map.get(MeetManageEntity.FieldNotremindusercode));
                List<String> notRemindUserCodesList = new ArrayList<>(Arrays.asList(notRemindUserCodes.split(",")));
                if (!StringUtil.isEmpty(manageUserCodes)) {
                    List<String> manageUserCodesList = new ArrayList<>(Arrays.asList(manageUserCodes.split(",")));
                    // 去掉不提醒的用户
                    manageUserCodesList.removeAll(notRemindUserCodesList);
                    // 防止大于1000项导致查询报错
                    this.spellWhereSQL("code", whereSql, manageUserCodesList);
                    whereSql.appendSingle(" and enabled = 1 ");
                    List<Map<String, Object>> userList = cboUserService.queryMapByWhere(whereSql.toString());
                    whereSql.clear();
                    // 拼接消息内容
                    String content = String.format(AppRemindTemplate.RemindUploadRecordContentTemplate1,
                            ConvertUtil.convertToString(map.get(MeetManageEntity.FieldName)));
                    userList.forEach(user -> pushList.add(createRemindTaskEntity(ConvertUtil
                            .convertToString(map.get("id")), subject, content, now, user)));
                } else if (!notRemindUserCodesList.contains(usercode)) {
                    whereSql.appendSingle(" code = '{0}' ", usercode);
                    List<Map<String, Object>> userList = cboUserService.queryMapByWhere(whereSql.toString());
                    whereSql.clear();
                    // 拼接消息内容
                    String content = String.format(AppRemindTemplate.RemindUploadRecordContentTemplate2,
                            cn.hutool.core.date.DateUtil.formatDateTime((Date) map.get(MeetManageEntity.FieldBegintime)),
                            ConvertUtil.convertToString(map.get(MeetManageEntity.FieldName)));
                    pushList.add(createRemindTaskEntity(ConvertUtil.convertToString(map.get("id")),
                            subject, content, now, userList.get(0)));
                }
            }
            // 批量更新提醒时间字段
            List<String> listFields = new ArrayList<>();
            listFields.add(MeetManageEntity.FieldRemindrecordlasttime);
            this.updateFieldsBatchMap(meetManageList, listFields);
            // 插入消息
            baseRemindTaskService.insertBatch(pushList);
        }
    }

    /**
     * @description: 拼接where条件，考虑in条件里大于1000项数据的情况
     * @author: chengengwei
     * @date: 2021-05-31
     * @modify:
     */
    private void spellWhereSQL(String col, StringBufferProxy whereSql, List<String> manageUserCodesList) {
        whereSql.appendSingle(" {0} in ( ", col);
        if (manageUserCodesList.size() > 999) {
            for (int i = 0; i < manageUserCodesList.size(); i++) {
                if (i % 999 == 0 && i > 0) {
                    whereSql = whereSql.substring(0, whereSql.length() - 1);
                    whereSql.appendSingle(" ) or code in ( '{1}',", manageUserCodesList.get(i));
                } else {
                    whereSql.appendSingle("'{0}',", manageUserCodesList.get(i));
                }
            }
            whereSql = whereSql.substring(0, whereSql.length() - 1);
            whereSql.appendSingle(" )");
        } else {
            whereSql.appendSingle("'" + manageUserCodesList.stream().collect(Collectors
                    .joining("','")) + "' )");
        }
    }

    /**
     * @description: 生成消息任务对象
     * @author: chengengwei
     * @date: 2021-02-23
     * @modify:
     */
    private BaseRemindTaskEntity createRemindTaskEntity(String id, String subject, String content, Date remindtime, Map<String, Object> user) {
        return createRemindTaskEntity(BaseSystemConst.BaseActionType.Remind, id, MeetManageEntity.tableName + "SummaryRemind", subject, content, remindtime, ConvertUtil.convertToString(user.get("code")),ConvertUtil.convertToString(user.get("name")));
    }

    /**
     * @return
     * @description: 判断当前登录用户是否可以进行签到
     * @author: chengengwei
     * @date: 2021-2-26
     * @modify:
     */
    @Override
    public Boolean isCanSign(String meetId) {
        MeetManageEntity meetManageEntity = this.queryById(meetId);
        LocalDateTime now = LocalDateTime.now();
        Date beginTime = meetManageEntity.getBegintime();
        if (beginTime != null) {
            LocalDateTime begintime = meetManageEntity.getBegintime().toInstant().atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            double start = ConvertUtil.convertToDouble(ParameterCache.getValue("ForbidSignForStart", "1"));
            LocalDateTime allowSignStartTime = begintime.minusMinutes((long) (start * 60));
            if (now.isBefore(allowSignStartTime)) {
                return false;
            }
        }
        Date endTime = meetManageEntity.getEndtime();
        if (endTime != null) {
            LocalDateTime endtime = meetManageEntity.getEndtime().toInstant().atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            double end = ConvertUtil.convertToDouble(ParameterCache.getValue("ForbidSignForEnd", "1"));
            LocalDateTime allowSignEndTime = endtime.plusMinutes((long) (end * 60));
            if (now.isAfter(allowSignEndTime)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @Description: 根据会议id查询所有的参会人员
     * @Author: mengmeng
     * @Date: 2021/5/28 14:22
     * @Version: 1.0
     */
    @Override
    public List<Map<String, Object>> queryUserByMeetId(long meetId) {
        if (meetId == 0) {
            throw new ServiceException("会议 ID 不能为空");
        }
        StringBufferProxy sqlWhere = new StringBufferProxy();
        sqlWhere.appendSingle(" sourcetype = '{0}' and sourceid = '{1}' and sourceflag = '{2}' ",
                MeetManageEntity.tableName, meetId, MeetPersonTypeEnum.Attend);
        List<BasePermissionManageEntity> basePermissionManageList = basePermissionManageService
                .queryByWhere(sqlWhere.toString());
        Map<String, Object> basePermissionMap = basePermissionManageService.processToMapUsers(basePermissionManageList);
        return basePermissionManageService.getAllAttendUser(basePermissionMap);
    }

    /**
     * @Description: 录音权限转让
     * @Author: mengmeng
     * @Date: 2021/6/1 14:51
     * @Version: 1.0
     */
    @Override
    @Transactional
    public void transferRecordAuthority(long meetId, String userCode) {
        if (meetId == 0 || StringUtil.isEmpty(userCode)) {
            throw new ServiceException("会议 ID 或者转让人员不能为空！");
        }
        StringBufferProxy sqlWhere = new StringBufferProxy();
        sqlWhere.appendSingle(" sourcetype = '{0}' and sourceid = '{1}' and sourceflag = '{2}' ",
                MeetManageEntity.tableName, meetId, MeetPersonTypeEnum.CanRecord);
        List<BasePermissionManageEntity> basePermissionManageList = basePermissionManageService
                .queryByWhere(sqlWhere.toString());

        if (CollectionUtils.isEmpty(basePermissionManageList)) {
            // 如果是空的需要新增
            BasePermissionManageEntity basePermissionManageEntity = new BasePermissionManageEntity();
            basePermissionManageEntity.setSourcetype(MeetManageEntity.tableName);
            basePermissionManageEntity.setSourceid(ConvertUtil.convertToString(meetId));
            basePermissionManageEntity.setSourceflag(MeetPersonTypeEnum.CanRecord);
            basePermissionManageEntity.setSharetype(BaseSystemConst.ShareTypeEnum.User);
            basePermissionManageEntity.setShareobjects(userCode);
            String userNames = getUserNamesByUserCode(userCode);
            basePermissionManageEntity.setShareobjectsdesc(userNames);
            basePermissionManageService.insert(basePermissionManageEntity);
        } else {
            // 修改原来的记录
            BasePermissionManageEntity basePermissionManageEntity = basePermissionManageList.get(0);
            String userCodes = basePermissionManageEntity.getShareobjects();
            // 去重
            Set<String> user = new HashSet<>(Arrays.asList(userCodes.split(",")));
            user.addAll(Arrays.asList(userCode.split(",")));
            String shareObjects = String.join(",", user);
            String userNames = getUserNamesByUserCode(shareObjects);
            basePermissionManageEntity.setShareobjects(shareObjects);
            basePermissionManageEntity.setShareobjectsdesc(userNames);
            basePermissionManageService.updateEntity(basePermissionManageEntity);
        }
    }

    /**
     * @Description: 根据当前用户作为发起人或者会议秘书查询名称模糊匹配的会议
     * @Author: mengmeng
     * @Date: 2021/6/3 9:57
     * @Version: 1.0
     */
    @Override
    public List<MeetManageEntity> queryByCondition(Map<String, Object> paraMap) {
        String userCode = ConvertUtil.convertToString(paraMap.get("currentuser"));
        if (StringUtil.isEmpty(userCode)) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>();
        param.put("masterUser", userCode);
        if (paraMap.containsKey("qry_name")) {
            param.put("meetName", paraMap.get("qry_name"));
        }
        return this.query(param, "selectMeetByCondition");
    }

    /**
     * @Description: 判断当前登录人对指定的会议是否已经参与
     * @Author: mengmeng
     * @Param: meetId
     * @Return:
     * @exception:
     * @Date: 2021/6/17 9:37
     * @Version: 1.0
     */
    @Override
    public boolean judgeCurrentUserAttendMeet(String meetId) {
        if (StringUtil.isEmpty(meetId)) {
            return false;
        }
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" sourcetype = '{0}' ", MeetManageEntity.tableName);
        sql.appendSingle(" and sourceid = '{0}' ", meetId);
        // 查询参会权限记录
        List<BasePermissionManageEntity> permissionManageEntityList = basePermissionManageService.queryByWhere(sql.toString());
        // 查询会议记录
        MeetManageEntity meetManageEntity = this.queryById(meetId);
        String manageUserCodes = meetManageEntity.getManageusercodes();
        List<String> meetManagerList = null;
        if (!StringUtil.isEmpty(manageUserCodes)) {
            meetManagerList = Arrays.asList(manageUserCodes.split(","));
        }
        // 根据权限记录转换成角色部门人员团队
        Map<String, Object> userMap = basePermissionManageService.processToMapUsers(permissionManageEntityList);
        // 转换成人员
        List<Map<String, Object>> allAttendUser = basePermissionManageService.getAllAttendUser(userMap);
        // 转换成人员code集合
        Set<String> userCodeSet = allAttendUser.stream().map(map -> ConvertUtil.convertToString(map.get("code"))).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(meetManagerList)) {
            userCodeSet.addAll(meetManagerList);
        }
        // 获取当前用户code
        String currentUserCode = this.getSessionUserBean().getUser().getCode();
        return userCodeSet.contains(currentUserCode);
    }

    private String getUserNamesByUserCode(String userCode) {
        List<Map<String, Object>> userList = baseCboUserExtendService.searchUsersByUserCodes(userCode);
        return userList.stream().map(item -> ConvertUtil.convertToString(item.get("name"))).collect(Collectors.joining(","));
    }

    /**
     * @Description: 生成会议的二维码
     * @Author: mengmeng
     * @Date: 2021/6/10 14:02
     * @Version: 1.0
     */
    private void generateMeetQRCode(String meetNum, String meetId) {
        if (StringUtil.isEmpty(meetNum)) {
            return;
        }
        QrConfig qrConfig = new QrConfig();
        String fileName = meetNum + ".PNG";
        File file = null;
        try {
            file = new File(fileName);
            Map<String, Object> content = new HashMap<>();
            content.put("sourceType", MeetManageEntity.tableName);
            content.put("meetNum", meetNum);
            content.put("meetId", meetId);
            String contentStr = JSONUtil.toJSONString(content);
            QrCodeUtil.generate(contentStr, qrConfig, file);
            Map<String, Object> param = new HashMap<>();
            param.put("sourceType", AttachmentMeetJoinSourceType);
            param.put("sourceId", meetNum);
            cboAttachmentService.executeUpload(param, file);
        } finally {
            if (file != null && file.exists()) {
                boolean deleted = file.delete();
            }
        }
    }

    /**
     * @description: 查询通过微前端集成创建的会议是否上传了会议纪要，如果存在
     * @author: chengengwei
     * @date: 2021-12-03
     * @modify:
     */
    @Override
    public Boolean queryUploadedRecordOfMicro(String sourcetype, long sourceid, String sourceapp) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("sourcetype", sourcetype);
        paramMap.put("sourceid", sourceid);
        paramMap.put("sourceapp", sourceapp);
        return this.getCount(paramMap, "queryUploadedRecordOfMicro") > 0;
    }

    /**
     * @param entity
     * @description: 为会议设置初始值
     * @author: donghang
     * @date: 2020年10月26日下午6:21:09
     * @modify:
     */
    @Override
    protected void beforeInsert(BasicEntity entity) {
        super.beforeInsert(entity);
        MeetManageEntity meetManageEntity = (MeetManageEntity) entity;
        meetManageEntity.setSignstate(BaseSystemConst.CboYesNoEnum.Yes);
    }

    /**
      * 向会议秘书+创建人发送消息。
      * @author xinfushuo
      * @date 2023/4/6
      * @modify
      */
    @Override
    public void sendMessageToMeetCreatorAndMessager(String meetid, String subject, String content, String action, String sourceType, String sourceId){
        MeetManageEntity entity = this.queryById(meetid);
        List<String> usernames = Arrays.stream((entity.getUsername() + "," + ConvertUtil.convertToString(entity.getManageusernames())).split(",")).filter(java.util.Objects::nonNull).filter(s->!s.isEmpty()).collect(Collectors.toList());
        List<String> usercodes = Arrays.stream((entity.getUsercode() + "," + ConvertUtil.convertToString(entity.getManageusercodes())).split(",")).filter(java.util.Objects::nonNull).filter(s->!s.isEmpty()).collect(Collectors.toList());
        for (int i = 0; i < usercodes.size(); i++) {
            baseRemindTaskService.insert(this.createRemindTaskEntity(action,sourceId,sourceType,subject,content,new Date(),usercodes.get(i),usernames.get(i)));
        }
    }
    public void replaceChangeMeetInfo(List<Map<String, Object>> tempList) {
        for (Map<String, Object> stringObjectMap : tempList) {
            //如果是发布变更中
            if (ConvertUtil.convertToInt(stringObjectMap.get("state")) == MeetStateEnum.SubmitChange){
                //查询有效的历史版本
                List<Map<String, Object>> historyList = meetManageHistoryService.queryMapByWhere(" meetid=" + ConvertUtil.convertToString(stringObjectMap.get("id")) + " and valid=1");
                if (historyList.size() > 0) {
                    for (String key : stringObjectMap.keySet()) {
                        if (historyList.get(0).containsKey(key) && !"id".equals(key)) {
                            stringObjectMap.put(key, historyList.get(0).get(key));
                        }
                    }
                }
            }
        }
        setDispFields(tempList);
    }
}
